class Solution 
{
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        // 1、初始化
        int n = words.size(), step = words[0].size();
        unordered_map<string, int> hash1, hash2;
        for(const auto& e : words) ++hash2[e];
        // 2、滑动窗口
        vector<int> ans;
        for(int i = 0 ; i < step; ++i)
        {
            for(int left = i, right = i, count = 0; right + step <= s.size(); right += step)
            {
                // 进窗口
                string in = s.substr(right, step);
                if(hash2.count(in) && ++hash1[in] <= hash2[in]) ++count;
                // 判断
                while(((right - left) / step + 1) > n)
                {
                    string out = s.substr(left, step);
                    if(hash2.count(out) && hash1[out]-- <= hash2[out]) --count;
                    left += step;
                }
                // 更新结果
                if(count == n) ans.push_back(left);
            }
            // 每完成一组滑动窗口，就重置 hash1
            hash1.clear();
        }
        // 3、返回值
        return ans;
    }
};